#include "hikari.h"

hash_map<long, HikariPersistHandler*>persistHandlers;
int parentId=-1;
int currentId=-1;
void addPersistanceHandler(wchar_t*key, HikariPersistHandler*handler);

HikariSceneLoader::HikariSceneLoader(){
	addPersistanceHandler(L"material", new MaterialLoadHandler());
	addPersistanceHandler(L"tfm", new TransformationLoadHandler());
	addPersistanceHandler(L"cube", new CubeLoadHandler());
	addPersistanceHandler(L"sphere", new SphereLoadHandler());
	addPersistanceHandler(L"cModel", new CustomModelLoadHandler());
	addPersistanceHandler(L"anim", new AnimationLoadHandler());
	addPersistanceHandler(L"cameraData", new CameraLoadHandler());
	addPersistanceHandler(L"camera", new CameraInstantiateLoadHandler());
	addPersistanceHandler(L"coneLight", new ConeLightLoadHandler());
	addPersistanceHandler(L"omniLight", new OmniLightLoadHandler());
	addPersistanceHandler(L"directionalLight", new DirectionalLightLoadHandler());
	addPersistanceHandler(L"lightSetting", new LightLoadHandler());
	addPersistanceHandler(L"script", new ScriptLoadHandler());
	addPersistanceHandler(L"billboard", new BillBoardLoadHandler());
	addPersistanceHandler(L"particle", new ParticleInstantiateLoadHandler());
	addPersistanceHandler(L"particleSetting", new ParticleLoadHandler());
}


HikariSceneLoader::~HikariSceneLoader(){
}

void addPersistanceHandler(wchar_t*key, HikariPersistHandler*handler){
	persistHandlers[Utils::hash_WString(key)]=handler;
}

HikariPersistHandler*getHandler(wstring&key){
	return persistHandlers[Utils::hash_WString(key)];
}

wstring getSceneFilePath(wstring&sceneName){
	return wstring(L"")+L"media\\scene\\"+sceneName+L".scn";
}

HObj*createObject(FileSection*section, HikariContext*context){
	wstring objectType=section->readString(section->getChunk(L"ObjT"));
	long hash = Utils::hash_WString(L"cube");
	hash=Utils::hash_WString(L"tfm");
	HikariPersistHandler*handler=getHandler(objectType);
	HObj*object=handler->read(context,NULL, section);
	if(object!=NULL){
		vector<Chunk*>attributes=section->getAllAttributes();
		for(unsigned int i=0;i<attributes.size();i++){
			if(Utils::equal(attributes[i]->getName(),L"parent")){
				parentId=section->readInt(attributes[i]);
			}else if(Utils::equal(attributes[i]->getName(),L"id")){
				currentId=section->readInt(attributes[i]);
			}else if(Utils::equal(attributes[i]->getName(),L"updtbl")){
				object->setUpdatealbe(section->readBoolean(attributes[i]));
			}
		}

		vector<Chunk*>sections=section->getAllSections();
		for(unsigned int i=0;i<sections.size();i++){
			Chunk*subSectionChunk=sections[i];
			HikariPersistHandler*subSectionHandler=getHandler(subSectionChunk->getName());
			if(subSectionHandler==NULL){
				wstring error=L"ERROR:Handler for object subsection ";
				wprintf(L"%s", (error + subSectionChunk->getName() + L" is not registered in system. Skipped.").c_str());
			}
			FileSection*subSection=section->readSection(subSectionChunk);
			object=subSectionHandler->read(context, object, subSection);
			delete subSection;
		}
	}
	return object;
}

void onSceneLoadOnUpdateableObjects(HikariContext*context){
	std::list<HObj*>&updateableObjects=context->getListOfUpdateableObjects();
	for(std::list<HObj*>::iterator i=updateableObjects.begin();i!=updateableObjects.end();i++){
		HObj*object=*i;
		vector<hComponent*>components=object->getComponentList();
		int length=components.size();
		for(int i=0;i<length;i++){
			hComponent*component=components[i];
			component->onSceneLoad(context, object);
		}
	}
}

bool HikariSceneLoader::loadScene(wstring sceneName, HikariContext*context){
	wstring path=getSceneFilePath(sceneName);
	HikariFileReader reader(path);
	vector<Chunk*>chunks=reader.getAllSections();
	for(unsigned int i=0;i<chunks.size();i++){
		Chunk*chunk=chunks[i];
		if(Utils::equal(chunk->getName(), L"3dObject")){
			FileSection*section=reader.readSection(chunk);
			HObj*object=createObject(section, context);
			if(object->isUpdateable()){
				context->addUpdateableObject(object);
			}
			delete section;
		}
	}
	onSceneLoadOnUpdateableObjects(context);
	return true;
}